package com.common.android.utils.smiley;

import java.lang.ref.WeakReference;
import java.util.ArrayList;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.os.Parcelable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.text.Editable;
import android.text.InputFilter;
import android.text.SpannableString;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.EditText;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.LinearLayout;

import com.common.android.utils.concurrent.NdExecutors;
import com.common.android.utils.db.CommonDaoFactory;
import com.nd.android.u.allcommon.R;
import com.product.android.business.ProductTypeDef.Product;
import com.product.android.business.config.Configuration;
import com.product.android.utils.MyPasteListener;
import com.product.android.utils.MyPasteListener.onPasteCatSmileyListener;

/**
 * ClassName:SmileyView Function: 表情管理类 Reason: TODO ADD REASON
 * 
 * @author cb
 * @version v1.3.x
 * @Date 2014 2014-1-10 下午2:54:31
 * 
 * @see
 */
@SuppressLint("NewApi")
public class SmileyView extends LinearLayout {
	private static final int MAX_HISTORY_COUNT = 24;
	public static final int MAX_INPUT_LEN = 500;
	private OnSmileyDelTouchListener mDelTouchListener;
	public boolean mIsTouchDel = false;// 是否按住删除表情

	private int mSmileyDrawableSize=0;

	/**
	 * GIF表情被点击后的回调接口
	 * <br>Created 2014-9-2 下午3:08:13
	 * @version  Ver 1.3.x
	 * @author   cb		
	 *
	 * @see 	 
	 * 
	 * Copyright(c) 2009-2014, TQ Digital Entertainment, All Rights Reserved
	 * 
	 */
	
	
	public interface OnSelectGifListener {
		void onSelectGifSmiley(Smiley smiley);
	}

	private OnSelectGifListener mSelectGifListener; // 选GIF表情监听
	private Context mContext;
    // 五个表情分类的按钮ID
    private int[] mIds = { 
            R.id.imgHistory, 
            R.id.imgNormal, 
            R.id.imgEmoji, 
            R.id.imgCos, 
            R.id.imgCat };

    // 表情分类按钮的选中态资源
    private int[] mSelectedDrawables = { 
            R.drawable.smiley_history_press,
            R.drawable.smiley_normal_press, 
            R.drawable.smiley_emoji_press,
            R.drawable.smiley_cos_press, 
            R.drawable.smiley_cat_press };

	// 表情分类按钮的普通态资源
	private int[] mUnSelectedDrawables = { 
	        R.drawable.smiley_history,
			R.drawable.smiley_normal,
			R.drawable.smiley_emoji,
			R.drawable.smiley_cos,
			R.drawable.smiley_cat };

	// 表情按钮
	private ArrayList<ImageView> mFunctionList = new ArrayList<ImageView>();

	// 表情分类数量
	private int mTotalCatagory;

	private ViewPager mPager;
	private int mCurrentSmileyCatagory = 0; // 当前显示的表情分类
	private int[] mCurrentItemIndexs; // 各个分类的当前页
	private int[] mPageSizes; // 各个分类的总页数
	private int[] mColumns; // 各个分类在GRID里面的列数
	private int[] mPageItems; // 各个分类在GRID里每一页显示的数量
	private LayoutInflater mInflater;
	private LinearLayout llNode; // 表情页切换用
	private EditText mEditText; // 点击表情后要显示表情的EDITTEXT
	private int mType; // 当前表情控件的使用环境：聊天/微博
	private boolean mbIsSwitchCatagory = false; // 是否切换分类操作
	private MyPasteListener mPasteListener;
	private int mMaxLength = 0;
	private static final int DEL_ONE = 1;// 删除一个表情或者文字
	private SmileyHandler mHandler;
	private boolean mIsInputLimited=false;
	public SmileyView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		init(context);
	}

	public SmileyView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
	}

	public SmileyView(Context context) {
		super(context);
		init(context);
	}

	private void init(Context context) {
		mContext = context;
		LayoutInflater.from(context)
				.inflate(R.layout.smiley_dialog, this, true);
	}

	/**
	 * @n<b>函数名称</b> :setParam
	 * @brief 设置参数
	 * @version Ver 1.3.3_modularization
	 * @param @param editText 选中某个表情后该表情要显示的edittext 其实应该是设置一个接口进来用于监听选中的表情。
	 *        鉴于目前所有的表情都是先显示在某个edittext上面，为减少调用方写的代码，直接把editText给传进来。
	 * @param @param type 表情的类型，见Smiley.TYPE_CHAT和Smiley.TYPE_WEIBO
	 * @return void
	 * @<b>作者</b> : cb
	 * @<b>创建时间</b> : 2014-3-11下午3:29:02
	 */
	public void setParam(EditText editText, int type) {
		mEditText = editText;
		mType = type;
		mInflater = (LayoutInflater) mContext
				.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		mEditText.addTextChangedListener(watcher);
		mPasteListener = new MyPasteListener(mContext);
		mPasteListener.setOnPasteCatSmileyListener(pasteCatSmileyListener);
		if (mIsInputLimited){
			mEditText.setFilters(new InputFilter[] { mPasteListener,
					new InputFilter.LengthFilter(MAX_INPUT_LEN) });	
		}else{
			mEditText.setFilters(new InputFilter[] { mPasteListener});
		}
		initView();
	}

	/**
	 * @n<b>函数名称</b> :setParam
	 * @brief 设置参数
	 * @version Ver 1.3.3_modularization
	 * @param editText
	 *            选中某个表情后该表情要显示的edittext 其实应该是设置一个接口进来用于监听选中的表情。
	 *            鉴于目前所有的表情都是先显示在某个edittext上面，为减少调用方写的代码，直接把editText给传进来。
	 * @param type
	 *            表情的类型，见Smiley.TYPE_CHAT和Smiley.TYPE_WEIBO
	 * @param maxLen
	 *            输入框支持输入的长度
	 * @return void
	 * @<b>作者</b> : chenqian
	 * @<b>创建时间</b> : 2014-3-11下午3:29:02
	 */
	public void setParam(EditText editText, int type, int maxLen) {
		setParam(editText, type);
		mMaxLength = maxLen;
		 // MyPasteListener 内增加下面这两个参数 -by wangds 2014.09.18
        mPasteListener.setType(type);
        mPasteListener.setMaxLength(maxLen);
	}

	/**
	 * @n<b>函数名称</b> :initView
	 * @brief 初始化控件
	 * @see
	 * @version Ver 1.3.x
	 * @param
	 * @return void
	 * @<b>作者</b> : cb
	 * @<b>创建时间</b> : 2014-1-10下午2:54:53
	 */
	private void initView() {
		mTotalCatagory = mIds.length;
		for (int i = 0; i < mTotalCatagory; i++) {
			setOnClickListener(mIds[i]);
		}
		mCurrentItemIndexs = new int[mTotalCatagory];
		mPageSizes = new int[mTotalCatagory];
		mColumns = new int[mTotalCatagory];
		mPageItems = new int[mTotalCatagory];
		initPageSize();

		mPager = (ViewPager) findViewById(R.id.viewpager);
		llNode = (LinearLayout) findViewById(R.id.llNode);
		mPager.setAdapter(adapter);
		mPager.setOnPageChangeListener(pageChangeListener);
		mHandler = new SmileyHandler(this);
		mDelTouchListener = new OnSmileyDelTouchListener();
	}

	/**
	 * @n<b>函数名称</b> :initPageSize
	 * @brief 初始化各表情分类的页数
	 * @see
	 * @version Ver 1.3.x
	 * @param
	 * @return void
	 * @<b>作者</b> : cb
	 * @<b>创建时间</b> : 2014-1-10下午2:55:20
	 */
	private void initPageSize() {
		for (int i = 0; i < mTotalCatagory; i++) {
			if (i == Smileyhelper.HISTORY || i == Smileyhelper.CAT || i == Smileyhelper.COS) {
				// 历史表情、英魂之刃表情和猫表情，每一页分四列
				mPageItems[i] = Smileyhelper.SIZE_CAT;
				mColumns[i] = Smileyhelper.COLUMNS_CAT;
			} else {
				// 其它表情每一页七列
				mPageItems[i] = Smileyhelper.SIZE_OTHER;
				mColumns[i] = Smileyhelper.COLUMNS_OTHER;
			}
			int total = Smileyhelper.getInstance().getSmileyList(i).size();
			mPageSizes[i] = (int) total / mPageItems[i]
					+ (total % mPageItems[i] == 0 ? 0 : 1);
		}
	}

	/**
	 * @n<b>函数名称</b> :showNode
	 * @brief 显示当前页
	 * @see
	 * @version Ver 1.3.x
	 * @param
	 * @return void
	 * @<b>作者</b> : cb
	 * @<b>创建时间</b> : 2014-1-10下午2:56:19
	 */
	private void showCurrentPage() {
		int count = llNode.getChildCount();
		// 取当前表情分类的总页数
		int pages = mPageSizes[mCurrentSmileyCatagory];
		for (int i = 0; i < pages; i++) {
			// 在页数范围内的圆点显示出来
			View view = llNode.getChildAt(i);
			view.setVisibility(View.VISIBLE);
			// 显示当前页
			if (i == mCurrentItemIndexs[mCurrentSmileyCatagory]) {
				view.setBackgroundResource(R.drawable.smiley_node_select);
			} else {
				view.setBackgroundResource(R.drawable.smiley_node_normal);
			}
		}
		// 页数范围之外的圆点隐藏
		for (int i = pages; i < count; i++) {
			llNode.getChildAt(i).setVisibility(View.GONE);
		}
	}

	/**
	 * @n<b>函数名称</b> :setOnClickListener
	 * @brief 为每一个表情分类按钮设置监听
	 * @see
	 * @version Ver 1.3.x
	 * @param @param id
	 * @return void
	 * @<b>作者</b> : cb
	 * @<b>创建时间</b> : 2014-1-10下午2:57:58
	 */
	private void setOnClickListener(int id) {
		ImageView img = (ImageView) findViewById(id);
		img.setOnClickListener(listener);
		mFunctionList.add(img);
	}

	private OnClickListener listener = new OnClickListener() {
		@Override
		public void onClick(View v) {
			int index = mFunctionList.indexOf(v);
			showSelection(index);
		}
	};

	/**
	 * @n<b>函数名称</b> :isShowing
	 * @brief 表情控件是否显示中
	 * @see
	 * @version Ver 1.3.x
	 * @param @return
	 * @return boolean
	 * @<b>作者</b> : cb
	 * @<b>创建时间</b> : 2014-1-10下午2:58:17
	 */
	public boolean isShowing() {
		return getVisibility() == View.VISIBLE;
	}

	/**
	 * @n<b>函数名称</b> :setShow
	 * @brief 设置表情控件是否显示
	 * @see
	 * @version Ver 1.3.x
	 * @param @param show
	 * @return void
	 * @<b>作者</b> : cb
	 * @<b>创建时间</b> : 2014-1-10下午2:58:33
	 */
	public void setShow(boolean show) {
		if (show) {
			setVisibility(View.VISIBLE);
		} else {
			setVisibility(View.GONE);
		}
	}

	/**
	 * @n<b>函数名称</b> :setonSelectGifListener
	 * @brief 设置GIF表情监听
	 * @see
	 * @version Ver 1.3.x
	 * @param @param listener
	 * @return void
	 * @<b>作者</b> : cb
	 * @<b>创建时间</b> : 2014-1-10下午2:58:42
	 */
	public void setOnSelectGifListener(OnSelectGifListener listener) {
		mSelectGifListener = listener;
	}

	/**
	 * @n<b>函数名称</b> :showSelection
	 * @brief 显示选中的表情分类
	 * @see
	 * @version Ver 1.3.x
	 * @param @param index
	 * @return void
	 * @<b>作者</b> : cb
	 * @<b>创建时间</b> : 2014-1-10下午2:58:52
	 */
	public void showSelection(int catagory) {
		if (mCurrentSmileyCatagory == catagory) {
			return;
		}
		// 保存上一个表情分类的当前页
		mCurrentItemIndexs[mCurrentSmileyCatagory] = mPager.getCurrentItem();
		mCurrentSmileyCatagory = catagory;
		for (int i = 0; i < mTotalCatagory; i++) {
			ImageView img = mFunctionList.get(i);
			if (i == mCurrentSmileyCatagory) {
				img.setBackgroundResource(R.drawable.smiley_select);
				img.setImageResource(mSelectedDrawables[i]);
			} else {
				img.setBackgroundResource(0);
				img.setImageResource(mUnSelectedDrawables[i]);
			}
		}
		if (mCurrentSmileyCatagory == Smileyhelper.HISTORY) {
			// 如果是历史表情，需要重新计算其页数
			int total = Smileyhelper.getInstance()
					.getSmileyList(mCurrentSmileyCatagory).size();
			mPageSizes[mCurrentSmileyCatagory] = (int) total
					/ mPageItems[mCurrentSmileyCatagory]
					+ (total % mPageItems[mCurrentSmileyCatagory] == 0 ? 0 : 1);
		}
		// 通知ADAPTER刷新
		mbIsSwitchCatagory = true;
		adapter.notifyDataSetChanged();
		mPager.setCurrentItem(mCurrentItemIndexs[mCurrentSmileyCatagory], false);
		showCurrentPage();
		mbIsSwitchCatagory = false;
	}

	private OnPageChangeListener pageChangeListener = new OnPageChangeListener() {
		@Override
		public void onPageSelected(int arg0) {
			// 在非切换表情分类操作的时候才保存当前的页码,因为在切换表情分类的时候,arg0是上一个表情分类的页码,如果保存下来会出错.
			if (mbIsSwitchCatagory) {
				mbIsSwitchCatagory = false;
			} else {
				mCurrentItemIndexs[mCurrentSmileyCatagory] = arg0;
			}
			showCurrentPage();
		}

		@Override
		public void onPageScrolled(int arg0, float arg1, int arg2) {
		}

		@Override
		public void onPageScrollStateChanged(int arg0) {
			mIsTouchDel = false;
		}
	};

	private PagerAdapter adapter = new PagerAdapter() {

		@Override
		public boolean isViewFromObject(View view, Object object) {
			return view == object;
		}

		@Override
		public int getCount() {
			return mPageSizes[mCurrentSmileyCatagory];
		}

		@Override
		public int getItemPosition(Object object) {
			return POSITION_NONE;
		}

		@Override
		public Object instantiateItem(ViewGroup container, int position) {
			LinearLayout ll = (LinearLayout) mInflater.inflate(
					R.layout.smiley_grid, null);
			GridView view = (GridView) ll.findViewById(R.id.gridview);
			view.setNumColumns(mColumns[mCurrentSmileyCatagory]);
			SmileyAdapter adapter = new SmileyAdapter(mContext,
					mCurrentSmileyCatagory);
			adapter.setPageNo(position);
			view.setAdapter(adapter);
			view.setOnItemClickListener(itemClickListener);
			view.setOnTouchListener(mDelTouchListener);
			container.addView(ll);
			return ll;
		}

		@Override
		public void destroyItem(ViewGroup container, int position, Object object) {
			container.removeView((View) object);
		}

		@Override
		public Parcelable saveState() {
			return null;
		}
	};

	@SuppressWarnings("unused")
	private OnItemLongClickListener onItemLongClickListener = new OnItemLongClickListener() {
		@Override
		public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
				int arg2, long arg3) {
			SmileyAdapter simpleAdapter = (SmileyAdapter) arg0.getAdapter();
			final Smiley smiley = (Smiley) simpleAdapter.getItem(arg2);
			if (smiley.id == 993) {
				mEditText.setText("");
			}
			return true;
		}
	};

	private OnItemClickListener itemClickListener = new OnItemClickListener() {
		@Override
		public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
				long arg3) {
			SmileyAdapter simpleAdapter = (SmileyAdapter) arg0.getAdapter();
			final Smiley smiley = (Smiley) simpleAdapter.getItem(arg2);
			if (checkDeleteSmiley(smiley)) {
				// 删除表情
				return;
			}
			int id = smiley.id;
			Drawable drawable=Smileyhelper.getInstance().getSmileyById(mContext, id);
			if (drawable != null) {
				// 可取到表情资源
				if (Smileyhelper.getInstance().isCatID(id) || Smileyhelper.getInstance().isCosID(id)) {
					// 是GIF的表情，直接发送
					if (mSelectGifListener != null) {
						mSelectGifListener.onSelectGifSmiley(smiley);
					}
				} else {
					// 普通表情
					Smileyhelper.getInstance().setSpannableToEditText(id,
							drawable, mEditText, mType, mMaxLength, mSmileyDrawableSize);
				}
				if (id != Smileyhelper.DEL_ID) {
					// 保存当前选中的表情到历史表情数据库
					NdExecutors.getCachedThreadPool().submit(new Runnable() {
						@Override
						public void run() {
							smiley.lastUsedTime = (System.currentTimeMillis());
							long result = CommonDaoFactory.getInstance()
									.getSmileyHistoryDao()
									.insertSmiley(smiley, MAX_HISTORY_COUNT);
							if (result == SmileyHistoryDao.DELETE_FAIL) {
								//
							} else {
								// 刷新历史表情
								Smileyhelper.getInstance()
										.refreshHistorySmiley();
							}
						}
					});

				}
			}
		}
	};

	/**
	 * @n<b>函数名称</b> :checkDeleteSmiley
	 * @brief 处理删除按钮
	 * @see
	 * @version Ver 1.3.x
	 * @param @param smiley
	 * @param @return
	 * @return boolean
	 * @<b>作者</b> : cb
	 * @<b>创建时间</b> : 2014-1-10下午3:00:45
	 */
	private boolean checkDeleteSmiley(Smiley smiley) {
		if (smiley.id == 993) {
			deleteOne();
			return true;
		}
		return false;
	}

	private TextWatcher watcher = new TextWatcher() {

		@Override
		public void beforeTextChanged(CharSequence s, int start, int count,
				int after) {
		}

		@Override
		public void onTextChanged(CharSequence s, int start, int before,
				int count) {
		}

		@Override
		public void afterTextChanged(Editable s) {
			SpannableString string = null;
			if (mPasteListener.getIsDoPaste() && !mPasteListener.getHasDone()) {
				if (mSmileyDrawableSize > 0) {
					string = Smileyhelper.getInstance()
							.getSmileySpannableString(s.toString(), mType,
									mSmileyDrawableSize);
				} else {
					string = Smileyhelper.getInstance()
							.getSmileySpannableString(s.toString(), mType);
				}
				mPasteListener.setIsDoPaste(false);
				mPasteListener.setHasDone(true);
				mEditText.setText(string);
			}
			int selection = Math.min(mPasteListener.getSelection(), mEditText
					.getText().length());
			mEditText.setSelection(selection);
		}
	};

	/**
	 * @n<b>函数名称</b> :hideCatagory
	 * @brief 隐藏某个表情分类的按钮
	 * @see
	 * @version Ver 1.3.x
	 * @param @param catagory 值定义在 SmileyHelper: SmileyHelper.HISTORY;
	 *        SmileyHelper.HISTORY; SmileyHelper.NORMAL; SmileyHelper.EMOJI;
	 *        SmileyHelper.CAT;
	 * @return void
	 * @<b>作者</b> : cb
	 * @<b>创建时间</b> : 2014-1-10下午3:13:24
	 */
	public void hideCatagory(int catagory) {
		mFunctionList.get(catagory).setVisibility(View.GONE);
	}

	/**
	 * @n<b>函数名称</b> :setIsShowSmileyFunc
	 * @brief 隐藏整个表情分类的按钮
	 * @see
	 * @version Ver 1.3.x
	 * @param @param show
	 * @return void
	 * @<b>作者</b> : cb
	 * @<b>创建时间</b> : 2014-1-10下午3:13:38
	 */
	public void setIsShowSmileyFunc(boolean show) {
		LinearLayout ll = (LinearLayout) findViewById(R.id.llFunction);
		if (!show) {
			ll.setVisibility(View.GONE);
		}
	}

	private onPasteCatSmileyListener pasteCatSmileyListener = new onPasteCatSmileyListener() {
		@Override
		public void onPasteCatSmiley(int id) {
			Smiley smiley = new Smiley();
			smiley.id = id;
			if (mSelectGifListener != null) {
				mSelectGifListener.onSelectGifSmiley(smiley);
			}
		}
	};

	class OnSmileyDelTouchListener implements OnTouchListener{
		int TIME = 150;// 隔多少时间删除一个文字

		@Override
		public boolean onTouch(View v, MotionEvent event) {
			if (event.getAction() == MotionEvent.ACTION_DOWN) {
				GridView view = (GridView) v;
				int index = view.pointToPosition((int) event.getX(),
						(int) event.getY());
				SmileyAdapter simpleAdapter = (SmileyAdapter) view.getAdapter();
				if (index < 0) {
					return false;
				}
				final Smiley smiley = (Smiley) simpleAdapter.getItem(index);
				// 如果点击在删除按键上，则连续删除
				if (null != smiley && smiley.id == 993) {
					mIsTouchDel = true;
					Thread t = new Thread() {
						@Override
						public void run() {
							super.run();
							while (mIsTouchDel) {
								try {
									Thread.sleep(TIME);
								} catch (InterruptedException e) {
									e.printStackTrace();
								}
								// 删除一个表情或文字
								if (mIsTouchDel) {
									mHandler.sendEmptyMessage(DEL_ONE);
								}
							}
						}
					};
					t.start();
				}
			} else if (event.getAction() == MotionEvent.ACTION_UP) {
				mIsTouchDel = false;
			}
			return false;
		}
	};

	static class SmileyHandler extends Handler {
		private WeakReference<SmileyView> mOuter;

		public SmileyHandler(SmileyView ctx) {
			mOuter = new WeakReference<SmileyView>(ctx);
		}

		public void handleMessage(Message msg) {
			SmileyView outer = mOuter.get();
			if (outer != null) {
				if (DEL_ONE == msg.what) {
					outer.deleteOne();
				}
			}
		}
	}

	private void deleteOne() {
		int keyCode = KeyEvent.KEYCODE_DEL; // 这里是退格键
		KeyEvent keyEventDown = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
		KeyEvent keyEventUp = new KeyEvent(KeyEvent.ACTION_UP, keyCode);
		mEditText.onKeyDown(keyCode, keyEventDown);
		mEditText.onKeyUp(keyCode, keyEventUp);
	}
	
	/**
	 * 增加输入限制
	 * <br>Created 2014-5-20 下午6:13:16
	 * @author       cb
	*/
	public void setInputLimited(){
		mIsInputLimited=true;
	}
	

	/**
	 * 设置表情图片的尺寸
	 * <br>Created 2014-9-22 下午8:40:19
	 * @param size 表情图片的尺寸,单位：DP
	 * @author  cb
	*/
	public void setSmileyDrawableSize(int size){
		if (size<0){
			mSmileyDrawableSize=0;
		}else{
			mSmileyDrawableSize=size;	
		}
	}
}
